#ifndef BOARDDEFINITIONS_H
#define BOARDDEFINITIONS_H

// bitboard variable -  example hex value 0xEE00FF00FF00FF00FF00FF00FF00FFAA where
// FFAA would be first rank and EE00 would be last (8) rank
/*
 RANKS:
   8 |       56   57   58   59   60   61   62   63  (MSB,
   7 |       48   49   50   51   52   53   54   55  left)
   6 |       40   41   42   43   44   45   46   47
   5 |       32   33   34   35   36   37   38   39
   4 |       24   25   26   27   28   29   30   31
   3 |       16   17   18   19   20   21   22   23
   2 |        8    9   10   11   12   13   14   15
   1 | (LSB,  0    1    2    3    4    5    6    7
       right)
           -------------------------------------------
 FILES:      a     b    c    d    e    f    g    h
*/

typedef unsigned long long U64;
typedef unsigned int size_t;
static const int A8 = 56; static const int B8 = 57; static const int C8 = 58; static const int D8 = 59;
static const int E8 = 60; static const int F8 = 61; static const int G8 = 62; static const int H8 = 63;
static const int A7 = 48; static const int B7 = 49; static const int C7 = 50; static const int D7 = 51;
static const int E7 = 52; static const int F7 = 53; static const int G7 = 54; static const int H7 = 55;
static const int A6 = 40; static const int B6 = 41; static const int C6 = 42; static const int D6 = 43;
static const int E6 = 44; static const int F6 = 45; static const int G6 = 46; static const int H6 = 47;
static const int A5 = 32; static const int B5 = 33; static const int C5 = 34; static const int D5 = 35;
static const int E5 = 36; static const int F5 = 37; static const int G5 = 38; static const int H5 = 39;
static const int A4 = 24; static const int B4 = 25; static const int C4 = 26; static const int D4 = 27;
static const int E4 = 28; static const int F4 = 29; static const int G4 = 30; static const int H4 = 31;
static const int A3 = 16; static const int B3 = 17; static const int C3 = 18; static const int D3 = 19;
static const int E3 = 20; static const int F3 = 21; static const int G3 = 22; static const int H3 = 23;
static const int A2 =  8; static const int B2 =  9; static const int C2 = 10; static const int D2 = 11;
static const int E2 = 12; static const int F2 = 13; static const int G2 = 14; static const int H2 = 15;
static const int A1 =  0; static const int B1 =  1; static const int C1 =  2; static const int D1 =  3;
static const int E1 =  4; static const int F1 =  5; static const int G1 =  6; static const int H1 =  7;

static const char* SQUARENAME[64] =  {"A1","B1","C1","D1","E1","F1","G1","H1",
                                      "A2","B2","C2","D2","E2","F2","G2","H2",
                                      "A3","B3","C3","D3","E3","F3","G3","H3",
                                      "A4","B4","C4","D4","E4","F4","G4","H4",
                                      "A5","B5","C5","D5","E5","F5","G5","H5",
                                      "A6","B6","C6","D6","E6","F6","G6","H6",
                                      "A7","B7","C7","D7","E7","F7","G7","H7",
                                      "A8","B8","C8","D8","E8","F8","G8","H8" };


static const U64 A_FILE = 0x0101010101010101ULL;
static const U64 B_FILE = 0x0202020202020202ULL;
static const U64 C_FILE = 0x0404040404040404ULL;
static const U64 D_FILE = 0x0808080808080808ULL;
static const U64 E_FILE = 0x1010101010101010ULL;
static const U64 F_FILE = 0x2020202020202020ULL;
static const U64 G_FILE = 0x4040404040404040ULL;
static const U64 H_FILE = 0x8080808080808080ULL;

static const U64 W_CASTLE_00_ATTACKS  = 0x0000000000000070ULL;
static const U64 W_CASTLE_000_ATTACKS = 0x000000000000001CULL;
static const U64 B_CASTLE_00_ATTACKS  = 0x7000000000000000ULL;
static const U64 B_CASTLE_000_ATTACKS = 0x1C00000000000000ULL;

// magic numbers for sliding pieces (files)
static const U64 FILE_MAGIC_ARRAY[8] = {   0x8040201008040200ULL,
                                           0x4020100804020100ULL,
                                           0x2010080402010080ULL,
                                           0x1008040201008040ULL,
                                           0x0804020100804020ULL,
                                           0x0402010080402010ULL,
                                           0x0201008040201008ULL,
                                           0x0100804020100804ULL, };

// shift for ranks (move generator uses this)
static const size_t RANKSHIFT[64] = {
        1,  1,  1,  1,  1,  1,  1,  1,
        9,  9,  9,  9,  9,  9,  9,  9,
       17, 17, 17, 17, 17, 17, 17, 17,
       25, 25, 25, 25, 25, 25, 25, 25,
       33, 33, 33, 33, 33, 33, 33, 33,
       41, 41, 41, 41, 41, 41, 41, 41,
       49, 49, 49, 49, 49, 49, 49, 49,
       57, 57, 57, 57, 57, 57, 57, 57
};

// magic multiplication numbers for diagonals (move generator uses this)
static const U64  _DIAGA8H1MAGICS[15] = {
       0x0,
       0x0,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0080808080808080,
       0x0040404040404040,
       0x0020202020202020,
       0x0010101010101010,
       0x0008080808080808,
       0x0,
       0x0
};

// magic multiplication numbers for diagonals (move generator uses this)
static const U64 _DIAGA1H8MAGICS[15] = {
       0x0,
       0x0,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x8080808080808000,
       0x4040404040400000,
       0x2020202020000000,
       0x1010101000000000,
       0x0808080000000000,
       0x0,
       0x0
};

// Piece identifiers, 4 bits each.
// Usefull bitwise properties of this numbering scheme:
// white = 0..., black = 1..., sliding = .1.., nonsliding = .0..
// rank/file sliding pieces = .11., diagonally sliding pieces = .1.1
// pawns and kings (without color bits), are < 3
// major pieces (without color bits set), are > 5
// minor and major pieces (without color bits set), are > 2
static const unsigned char EMPTY = 0;                //  0000
static const unsigned char WHITE_PAWN = 1;           //  0001
static const unsigned char WHITE_KING = 2;           //  0010
static const unsigned char WHITE_KNIGHT = 3;         //  0011
static const unsigned char WHITE_BISHOP =  5;        //  0101
static const unsigned char WHITE_ROOK = 6;           //  0110
static const unsigned char WHITE_QUEEN = 7;          //  0111
static const unsigned char BLACK_PAWN = 9;           //  1001
static const unsigned char BLACK_KING = 10;          //  1010
static const unsigned char BLACK_KNIGHT = 11;        //  1011
static const unsigned char BLACK_BISHOP = 13;        //  1101
static const unsigned char BLACK_ROOK = 14;          //  1110
static const unsigned char BLACK_QUEEN = 15;         //  1111

static bool WHITE_TO_MOVE = true;
static bool BLACK_TO_MOVE = false;
static const unsigned char WHITE_00_CASTLING_MOVE = 1;
static const unsigned char WHITE_000_CASTLING_MOVE = 2;
static const unsigned char BLACK_00_CASTLING_MOVE = 3;
static const unsigned char BLACK_000_CASTLING_MOVE = 4;

// Value of material, in centipawns:
static const int PAWN_VALUE = 100;
static const int KNIGHT_VALUE = 300;
static const int BISHOP_VALUE = 325;
static const int ROOK_VALUE = 500;
static const int QUEEN_VALUE = 950;
static const int KING_VALUE = 29999;
static const int CHECK_MATE = KING_VALUE;
static const int STALE_MATE = 0;
static const int INFINITY = 29999; // keeping within 32-bit integer boundaries

// value patterns (simple static ones)
static const U64 ROOK_VALUE_PATTERN   = 0xFF000000000000FFULL;
static const U64 KNIGHT_VALUE_PATTERN = 0x000000FFFF000000ULL;


inline bool ISIN(size_t val, size_t low, size_t high)
{
    return ((val >= low) && (val <= high)) ? true : false;
}

// helper functions used for KNIGHT_ATTACKS precalc
inline size_t RANKDIFF(size_t first, size_t second)
{
    // get ranks
   int rank_first = (first / 8) + 1;
   int rank_second = (second / 8) + 1;

   return (rank_first >= rank_second) ? (rank_first - rank_second) : (rank_second - rank_first);
}
inline size_t FILEDIFF(size_t first, size_t second)
{
    // get files
   int file_first = (first % 8) + 1;
   int file_second = (second % 8) + 1;

   return (file_first >= file_second) ? (file_first - file_second) : (file_second - file_first);
}

#endif // BOARDDEFINITIONS_H
